home *** CD-ROM | disk | FTP | other *** search
-
- In article <1992Apr13.183936.3762@news.uni-stuttgart.de> you wrote:
-
- >Hi
- >
- >A few weeks ago, someone told here, that he wrote a tool for preemptive
- >multitasking and will public it in comp.binaries.acorn.
- >Unfortunatly comp.binaries.acorn is closed for a while. Could someone
- >give me informations about the author ?
-
- It's included here...
-
- >thanks
- >so long
- >MUFTI
- >
- >ps:
- > Shouldn't the moderator of comp.binaries.acorn lay a forward to
- > one of the ftp/mail-servers, if he isn't on duty for a long time ?
- > The software he gets is not for private Acorn ltd. use .....
-
- We could forward all stuff to Albert at Newcastle. The reasons that
- nothing has been posted for a while are as follows:-
-
- a) Phil Colmer is ill at present; he would normally handle
- comp.sources.acorn
-
- b) Alan Glover and myself are v. busy right now. I expect to
- begin posting things again soon, maybe withing the next week
- or two. As for Alan, I don't know. Unfortunately, moderating
- comp.*.acorn isn't really seen as part as the 'job' that we
- do here, so it has to be a spare time activity.
-
- Chris.
-
- ______________________________________________________________________
- Chris Marshall cmarshall@acorn.co.uk
-
- >From pc123@phx.cam.ac.uk Tue Feb 25 19:29:59 1992
- Received: by oak.acorn.co.uk (4.1/Ai1.6)
- id AA11229; Tue, 25 Feb 92 19:29:56 GMT
- Received: by acorn.co.uk (4.1/Am32)
- id AA13477; Tue, 25 Feb 92 19:29:02 GMT
- Received: from phx.cam.ac.uk by eros.uknet.ac.uk via JANET with NIFTP (PP)
- id <25975-0@eros.uknet.ac.uk>; Tue, 25 Feb 1992 18:22:59 +0000
- Date: Tue, 25 Feb 92 18:22:08 GMT
- >From: Pete <pc123@phx.cam.ac.uk>
- To: submit@acorn.co.uk
- Subject: Code for pre-empting a non-desktop task
- Message-Id: <A54D6B55FDE90040@UK.AC.CAMBRIDGE.PHOENIX>
-
- Newsgroups: comp.sources.acorn
-
- Here is the code to demonstrate how you can pre-empt a non-desktop program
- without running it in a taskwindow or under FrontEnd, as I promised on c-s-a
- recently. The code implements a module which acts a bit like FrontEnd but is a
- tinsy bit more efficient in its use of RMA; it should be possible to convert it
- for multitasking raytracers or other code you are writing without too much
- difficulty.
-
- The module writes all output generated by the program into a circular buffer at
- a fixed offset in its workspace - a desktop task then uses the OS_Module call
- to find out where the workspace is, and reads data out. The effect is that
- text produced by a program is not stored in the RMA, so excessive fragmentation
- does not occur. This also implies that this module is only the "business end"
- of a complete FrontEnd replacement, and you have to write a desktop client
- program as well, to display output produced by a task in a window. I am not
- posting the client here, because this source is really for illustration only.
-
- The module also allows the task it is running to be stopped and restarted under
- control of the controlling program. This is accomplished by writing various
- values into another word at a fixed offset in the module's workspace.
- Similarly the module may be asked to kill the program it is pre-empting (never
- scheduling it again, and closing all its files) or terminate it (call its exit
- handler).
-
- As I wrote Express Assembler, the module is written in Express format. You
- shouldn't have too much trouble understanding it, as it does not use any fancy
- features.
-
- It is well known that only Quiche Eaters comment their programs well. I have
- added a few, but...
-
- ...if you find you need help following it, send me mail and I will do my best
- to help. Or flame about it on c-s-a instead :-) .
-
-
- SETTYPE "MODULE"
- OBJECT "!YAMU.Initiator"
- ORG 0
- ASSUME PC,0
- ASSUME R12,&10000000
-
- SET VSTR,"1.00"
-
- DD LANGUAGE,0,0,SERVICE,TITLE,HELP,0,0,0,0,0
-
- TITLE DB "Initiator",0
- ALIGN
-
- HELP DB "Initiator",9,"`VSTR` (",OSVAR "Sys$Date" RIGHT 6," ",OSVAR "Sys$Year",")",0
- ALIGN
-
- TASKDESC
- DB "Init",0
- ALIGN
-
- LANGUAGE
- LOCALS
- MOV R11,R0
-
- ; Claim memory
-
- MOV R0,#6
- LIT R3,WEND-WSTART
- SWI "OS_Module"
- STR R2,[R12]
- STR R12,[R2]
- MOV R12,R2
-
- ; Initialise variables
-
- MOV R0,#0
- ST R0,MEMORYMAPVETOED
- ST R0,OUTBUFFERREAD
- ST R0,OUTBUFFERWRITE
- ST R0,MESSAGES
- ST R0,SUSPENDED
- ST R0,TERMINATING
- ST R0,HANDLESUSED
-
- ; Register as Wimp task
-
- MOV R0,#200
- LIT R1,&4B534154
- ADR R2,TASKDESC
- SWI "Wimp_Initialise"
- ST R1,TASKHANDLE
-
- ; Calculate appropriate (initial) slot size. This is not calculated
- ; in any special way, it just tries to allocate a reasonable amount
- ; of space. The newer applications ask the Wimp for more space if
- ; they run out.
-
- MVN R0,#0
- MVN R1,#0
- SWI "Wimp_SlotSize"
- ADD R0,R0,R1
- ADD R0,R0,R2
- CMP R0,#512*1024
- MOVGE R0,#512*1024
- SUBLT R0,R0,#64*1024
- CMP R0,#0
- MOVLE R0,#16*1024
- MVN R1,#0
- SWI "Wimp_SlotSize"
-
- ; Initialise environment, so that funny things don't happen when the
- ; background task calls the exit handler, etc. In fact the exit
- ; handler has to come back into this code in order for us to tidy up.
-
- MOV R0,#6 ; Error handler
- ADR R1,ERRORHANDLER
- MOV R2,R12
- ADR R3,ERRORBUFFER
- SWI "OS_ChangeEnvironment"
- ADR R0,OLDERRORHANDLER
- STMIA R0,{R1-R3}
-
- MOV R0,#11 ; Exit handler
- ADR R1,EXITHANDLER
- MOV R2,R12
- MOV R3,#0
- SWI "OS_ChangeEnvironment"
- ADR R0,OLDEXITHANDLER
- STMIA R0,{R1-R3}
-
- ; Set interruption of background task
-
- BL SETCALLAFTER
- BL CLAIMVECS
-
- ; And start the task off
-
- MOV R0,R11
- SWI "OS_Write0" ; This just writes the name of the command
- SWI "OS_NewLine" ; run into the output buffer.
- MOV R0,R11
- SWI "OS_CLI" ; Execute the * command that runs the task.
-
- ; This may return, if no application is started. In this case, there
- ; is an outstanding ticker event to cancel, but apart from that we
- ; just exit.
-
- ADR R13,USRSTACK
- BL CANCELTICKER ; Cancel the descheduling time-out.
- BL RELEASEVECS ; Release vectors we have claimed.
- B KILLMODULE
-
- MAINLOOP
- BL RELEASEVECS ; Must release all vectors before polling.
- A
- MOV R0,#0
- ADR R1,POLLBLOCK
- SWI "Wimp_Poll"
- TEQ R0,#0
- BLNE NONIDLEPOLL
- ADR R13,USRSTACK
- BL RECEIVEMESSAGES
- BNE A
-
- ; See whether the output buffer is empty - if not we wait until it
- ; has been emptied before running the task again.
-
- LD R0,OUTBUFFERREAD
- LD R1,OUTBUFFERWRITE
- TEQ R0,R1
- BNE A
-
- ; If the task has been stopped by the controlling task, don't
- ; reschedule it.
-
- LD R0,SUSPENDED
- TEQ R0,#0
- BNE A
-
- ; Set up conditions for re-entering task
-
- BL SETCALLAFTER ; Create a new CallAfter event
- BL CLAIMVECS ; and claim the vectors again.
-
- ; If the task is being terminated, get ready to call OS_Exit
-
- LD R0,TERMINATING
- TEQ R0,#0
- MOV R0,#0
- ST R0,TERMINATING
-
- ; Back into the task again. When restoring the registers, note that
- ; the correct method for doing this is very dependent on the current
- ; processor mode - what is shown is NOT a general way of restoring
- ; a register dump after an exception.
-
- ADR R0,REGBUF
- LDMEQIA R0,{R0-PC}^ ; Restore the task's registers.
- LDMIA R0,{R0-R14}
- MOV R0,#0
- LIT R1,&58454241
- MOV R2,#2
- SWI "OS_Exit" ; Task is being terminated. Note how we can
- ; even call OS_Exit "within" a CallBack handler.
-
- ; General rubbish to do with being a Wimp task, nothing amazing here.
-
- NONIDLEPOLL
- TEQ R0,#17
- TEQNE R0,#18
- MOVNES PC,R14
- LD R0,POLLBLOCK+16
- TEQ R0,#0 ; Message_Quit
- MOVNES PC,R14
- ADR R13,USRSTACK
- BL CANCELTICKER
- MOV R0,#0
- ST R0,OUTBUFFERREAD
- ST R0,OUTBUFFERWRITE
-
- ; and continue into KILLMODULE, below.
-
- ; Code to kill the module off. Nothing here that you don't get in
- ; other modules, the only point worthy of note is that we hang around
- ; in this routine until all the characters have been read out of the
- ; circular buffer.
-
- KILLMODULE
- LOCALS
-
- ; Restore environment
-
- MOV R0,#6 ; Error handler
- ADR R1,OLDERRORHANDLER
- LDMIA R1,{R1-R3}
- SWI "OS_ChangeEnvironment"
-
- MOV R0,#11 ; Exit handler
- ADR R1,OLDEXITHANDLER
- LDMIA R1,{R1-R3}
- SWI "OS_ChangeEnvironment"
-
- ; Write the return code into the message word, for the foreground
- ; task
-
- LD R0,RETURNCODE
- ORR R0,R0,#&80000000
- ST R0,MESSAGES
-
- ; Now call Wimp_Poll until all the characters have been removed from
- ; the buffer and the return code has been read
-
- A
- MOV R0,#0
- ADR R1,POLLBLOCK
- SWI "Wimp_Poll"
- LD R0,OUTBUFFERREAD
- LD R1,OUTBUFFERWRITE
- TEQ R0,R1
- BNE A
- LD R0,MESSAGES
- TEQ R0,#0
- BNE A
-
- ; Finish off as a Wimp task
-
- LD R0,TASKHANDLE
- LIT R1,&4B534154
- SWI "Wimp_CloseDown"
-
- ; Release workspace
-
- MOV R0,#7
- MOV R2,R12
- SWI "OS_Module"
-
- ; Zero private word so RISC OS doesn't free it again!!
-
- LD R0,PRIVATEWORD
- MOV R1,#0
- STR R1,[R0]
-
- ; ExitAndDie to end program and kill module; don't set return code
- ; as this was set by foreground task.
-
- MOV R0,#0
- MOV R1,#0
- MOV R2,#0
- ADR R3,TITLE
- SWI "OS_ExitAndDie"
-
- ; Just a standard service call handler. Traps Service_Memory so we
- ; get to keep the memory that the pre-empted task will run in!
-
- SERVICE
- ; Nothing to do here except veto attempts by the Wimp to remove all
- ; our memory - this is tried once at the start.
-
- TEQ R1,#&11 ; Service_Memory
- MOVNES PC,R14
- STMFD R13!,{R0,R12,R14}
- LDR R12,[R12]
- LD R0,MEMORYMAPVETOED
- TEQ R0,#0
- LDMNEFD R13!,{R0,R12,PC}^
- MOV R1,#0
- MOV R0,#1
- ST R0,MEMORYMAPVETOED
- LDMFD R13!,{R0,R12,PC}^
-
- ; Claim write character (so we redirect the program's output into
- ; the circular buffer) and open file (so we know what files the
- ; program has open, so we can close them again if it is killed).
-
- CLAIMVECS
- MOV R0,#3 ; WrchV
- ADR R1,WRCHV
- MOV R2,R12
- SWI "OS_Claim"
-
- MOV R0,#&D ; FindV
- ADR R1,FINDV
- MOV R2,R12
- SWI "OS_Claim"
-
- MOVS PC,R14
-
- RELEASEVECS
- MOV R0,#3 ; WrchV
- ADR R1,WRCHV
- MOV R2,R12
- SWI "OS_Release"
-
- MOV R0,#&D ; FindV
- ADR R1,FINDV
- MOV R2,R12
- SWI "OS_Release"
-
- MOVS PC,R14
-
- ; Schedule a descheduling event.
-
- SETCALLAFTER
- MOV R0,#20
- ADR R1,INTERRUPT
- MOV R2,R12
- SWI "OS_CallAfter"
- MOVS PC,R14
-
- CANCELTICKER
- STMFD R13!,{R0,R1,R14}
- ADR R0,INTERRUPT
- MOV R1,R12
- SWI "OS_RemoveTickerEvent"
- LDMFD R13!,{R0,R1,PC}^
-
- WRCHV
- STMFD R13!,{R1-R2}
- LD R1,OUTBUFFERREAD
- LD R2,OUTBUFFERWRITE
- ADD R2,R2,#2
- BIC R2,R2,#&400
- TEQ R1,R2
- BLEQ CANCELTICKER
- BLEQ SETCALLBACK
- LD R1,OUTBUFFERWRITE
- ADR R2,OUTBUFFER
- STRB R0,[R1,R2]
- ADD R1,R1,#1
- BIC R1,R1,#&400
- ST R1,OUTBUFFERWRITE
- LDMFD R13!,{R1-R2}
- LDMFD R13!,{PC}^
-
- FINDV
- LOCALS
- TEQ R0,#0 ; Closing a file
- BEQ A
- STMFD R13!,{R12}
- STMFD R13!,{PC}
- MOVS PC,R14
- MOV R0,R0 ; Our code is re-entered a word further down, so we waste
- ; this word.
- LDMFD R13!,{R12}
- LDMVSFD R13!,{PC}
- STMFD R13!,{R2,R3}
- ADR R2,HANDLES
- LD R3,HANDLESUSED
- TEQ R3,#32
- MOVEQ R3,#31
- STR R0,[R2,R3,LSL #2]
- ADD R3,R3,#1
- ST R3,HANDLESUSED
- LDMFD R13!,{R2,R3}
- LDMFD R13!,{PC}^
- A
- TEQ R1,#0 ; Closing all files
- BEQ B
- STMFD R13!,{R2,R8,R9,R14}
- LD R8,HANDLESUSED
- ADR R9,HANDLES
- C
- TEQ R8,#0
- LDMEQFD R13!,{R2,R8,R9,PC}^
- LDR R2,[R9],#4
- SUB R8,R8,#1
- TEQ R1,R2
- BNE C
- MOV R2,#0
- STR R2,[R9,#-4]
- LDMFD R13!,{R2,R8,R9,PC}^
- B
- STMFD R13!,{R0,R14}
- MOV R0,#0
- ST R0,HANDLESUSED
- LDMFD R13!,{R0,PC}^
-
- INTERRUPT
- ; Remember that we must not corrupt R14svc, so we have to mess about
- ; with changing processor mode.
-
- STMFD R13!,{R0,R14} ; R14irq goes onto irq stack.
- MOVS R0,PC ; Preserve old processor mode.
- TEQP PC,#3
- MOV R0,R0
- STMFD R13!,{R14}
- BL SETCALLBACK ; Use CallBack code.
- LDMFD R13!,{R14}
- TEQP R0,#0
- MOV R0,R0
- LDMFD R13!,{R0,PC}^
-
- ; The following is just standard CallBack code, it restores the
- ; handler address to its old value before returning to the main
- ; program loop.
-
- SETCALLBACK
- STMFD R13!,{R0-R3,R14}
- MOV R0,#7 ; CallBack
- ADR R1,CALLBACKHANDLER
- MOV R2,R12
- ADR R3,REGBUF
- SWI "OS_ChangeEnvironment"
- ADR R14,OLDCALLBACK
- STMIA R14,{R1-R3}
- SWI "OS_SetCallBack"
- LDMFD R13!,{R0-R3,PC}^
-
- CALLBACKHANDLER
- TEQP PC,#0
- MOV R0,R0
- MOV R0,#7
- ADR R1,OLDCALLBACK
- LDMIA R1,{R1-R3}
- SWI "OS_ChangeEnvironment"
- B MAINLOOP
-
- ; If we get an error reported, we write it into the circular buffer
- ; and kill the program.
-
- ERRORHANDLER
- MOV R12,R0
- MOV R0,#2
- ST R0,RETURNCODE
- SWI "OS_NewLine"
- ADR R0,ERRORBUFFER+8
- SWI "OS_Write0"
- SWI "OS_NewLine"
- ADR R13,USRSTACK
- BL CANCELTICKER
- BL RELEASEVECS
- B KILLMODULE
-
- ; If the program exits, we tidy up.
-
- EXITHANDLER
- ST R2,RETURNCODE
- ADR R13,USRSTACK
- BL CANCELTICKER
- BL RELEASEVECS
- B KILLMODULE
-
- ; These messages control the pre-empted task. They allow the
- ; controlling process to stop and restart it, terminate it (which
- ; invokes the program's exit handler) and kill it (which will never
- ; reschedule it, and just closes all its files before shutting down).
-
- RECEIVEMESSAGES
- LOCALS
- STMFD R13!,{R0,R14}
- LD R0,MESSAGES
- STMFD R13!,{R0}
- TST R0,#&80000000
- MOVEQ R0,#0
- ST R0,MESSAGES
- LDMFD R13!,{R0}
- TEQ R0,#1 ; Suspend
- BEQ A
- TEQ R0,#2 ; Restart
- BEQ B
- TEQ R0,#3 ; Terminate
- BEQ C
- TEQ R0,#4 ; Kill
- BEQ D
- LDMFD R13!,{R0,PC}^
- A
- MOV R0,#1
- ST R0,SUSPENDED
- LDMFD R13!,{R0,PC}^
- B
- MOV R0,#0
- ST R0,SUSPENDED
- LDMFD R13!,{R0,PC}^
- C
- MOV R0,#1
- ST R0,TERMINATING
- LDMFD R13!,{R0,PC}^
- D
- MOV R9,#0
- LD R10,HANDLESUSED
- ADR R11,HANDLES
- E
- TEQ R10,#0
- BEQ F
- MOV R0,#0
- LDR R1,[R11],#4
- TEQ R1,#0
- ADDNE R9,R9,#1
- SWINE "OS_Find"
- SUB R10,R10,#1
- B E
- F
- BL CLAIMVECS
- SWI "OS_WriteS"
- DB 13,10,10,"Killed",13,10,0
- ALIGN
- MOV R0,R9
- ADR R1,ERRORBUFFER
- MOV R2,#16
- SWI "OS_ConvertCardinal4"
- SWI "OS_Write0"
- SWI "OS_WriteS"
- DB " file(s) closed",13,10,0
- ALIGN
- BL RELEASEVECS
- MOV R0,#2
- ST R0,RETURNCODE
- B KILLMODULE
-
- DSECT
- ORG &10000000
- WSTART
-
-
- PRIVATEWORD ALLOC 4
- MESSAGES ALLOC 4 ; Messages are written here by a controlling
- ; task.
- OUTBUFFERREAD ALLOC 4
- OUTBUFFERWRITE ALLOC 4
- OUTBUFFER ALLOC 1024 ; The output circular buffer
- TASKHANDLE ALLOC 4
- MEMORYMAPVETOED ALLOC 4
- SUSPENDED ALLOC 4
- TERMINATING ALLOC 4
- HANDLESUSED ALLOC 4
- RETURNCODE ALLOC 4
- REGBUF ALLOC 4*16
- OLDCALLBACK ALLOC 4*3
- OLDERRORHANDLER ALLOC 4*3
- OLDEXITHANDLER ALLOC 4*3
- HANDLES ALLOC 4*32
- POLLBLOCK ALLOC 256
- ERRORBUFFER ALLOC 256+4+4
-
- ALLOC 64
- USRSTACK
-
-
- WEND
- DEND
-
- END
-
-